<?php
/** 
* Auto Login Component
*
* A CakePHP Component that will automatically login the Auth session for a duration if the user requested to (saves data to cookies). 
*
* @author       Miles Johnson - http://milesj.me
* @copyright    Copyright 2006-2010, Miles Johnson, Inc.
* @license      http://opensource.org/licenses/mit-license.php - Licensed under The MIT License
* @link         http://milesj.me/resources/script/auto-login-component
*
* Modificato da Stefano Zoffoli:
* - il cookie non salva più informazioni sensibili come email e password, ma solo l'id dell'utente
* - aggiunta di una funzione per generare la firma del cookie in base all'id dell'utente
* - la firma del cookie tiene conto anche dello user-agent per prevenire furti di identità
* - varie modifiche per migliorare le performance
*/

class AutoLoginComponent extends Object {

	/**
	 * Current version: http://milesj.me/resources/logs/auto-login-component
	 *
	 * @access public
	 * @var string
	 */
	public $version = '2.0-sz';

	/**
	 * Cookie name.
	 *
	 * @access public
	 * @var string
	 */
	public $cookieName = 'autoLogin';

	/**
	 * Cookie length (strtotime()).
	 *
	 * @access public
	 * @var string
	 */
	public $expires = '+2 weeks';

	/**
	 * Settings.
	 *
	 * @access public
	 * @var array
	 */
	public $settings = array();

	/**
	 * Automatically login existent Auth session; called after controllers beforeFilter() so that Auth is initialized.
	 *
	 * @access public
	 * @param object $Controller
	 * @return boolean
	 */
	public function startup($Controller) {
		$this->Controller = $Controller;
		$this->Auth = $this->Controller->Auth;

		if (isset($this->Controller->Cookie)) {
			$this->Cookie = $this->Controller->Cookie;
		}

		if (!isset($this->Cookie)) {
			App::import('Component', 'Cookie');

			$this->Cookie = new CookieComponent();
			$this->Cookie->initialize($Controller, array());
		}

		if ($this->Auth->user()) {
			return;
		}

		$cookie = $this->Cookie->read($this->cookieName);
		if (!is_array($cookie) || $cookie['signature'] != $this->generate_signature($cookie['user_id'])) {
			$this->delete();
			return;
		}

		if ($this->Auth->login($cookie['user_id'])) {
			if (in_array('_autoLogin', get_class_methods($this->Controller))) {
				$user = $this->Auth->user();
				call_user_func_array(array($this->Controller, '_autoLogin'), array($user));
			}
		} else {
			if (in_array('_autoLoginError', get_class_methods($this->Controller))) {
				call_user_func_array(array($this->Controller, '_autoLoginError'), array($cookie));
			}
		}
		return;
	}

	/**
	 * Automatically process logic when hitting login/logout actions.
	 *
	 * @access public
	 * @uses Inflector
	 * @param object $Controller
	 * @return void
	 */
	public function beforeRedirect($Controller) {
		$this->settings = $this->settings + array(
			'plugin' => '',
			'controller' => '',
			'loginAction' => 'login',
			'logoutAction' => 'logout'
		);

		if (is_array($this->Auth->loginAction)) {
			if (!empty($this->Auth->loginAction['controller'])) {
				$this->settings['controller'] = Inflector::camelize($this->Auth->loginAction['controller']);
			}

			if (!empty($this->Auth->loginAction['action'])) {
				$this->settings['loginAction'] = $this->Auth->loginAction['action'];
			}
		}

		if (!empty($this->Auth->userModel) && empty($this->settings['controller'])) {
			$this->settings['controller'] = Inflector::pluralize($this->Auth->userModel);
		}

		// Is called after user login/logout validates, but befire auth redirects
		if ($this->Controller->plugin == $this->settings['plugin'] && $this->Controller->name == $this->settings['controller']) {
			$data = $this->Controller->data;

			switch ($this->Controller->action) {
				case $this->settings['loginAction']:
					if (isset($data[$this->Auth->userModel])) {
						$formData = $data[$this->Auth->userModel];
						$username = $formData[$this->Auth->fields['username']];
						$password = $formData[$this->Auth->fields['password']];
						$autoLogin = ($formData['auto_login'] != 0);

						if ($autoLogin && $this->Auth->login($formData)) {
							$user_id = $this->Auth->user('id');
							$this->save($user_id);
						} else {
							$this->delete();
						}
					}
				break;

				case $this->settings['logoutAction']:
					$this->delete();
				break;
			}
		}
	}

	/**
	 * Remember the user information.
	 *
	 * @access public
	 * @param integer $user_id
	 * @return void
	 */
	public function save($user_id) {
		$cookie = array();
		$cookie['user_id'] = $user_id;
		$cookie['signature'] = $this->generate_signature($user_id);

		$this->Cookie->write($this->cookieName, $cookie, true, $this->expires);
	}

	/**
	 * Genera la firma del cookie in base all'id dell'utente.
	 *
	 * @param <type> $user_id
	 * @return <type>
	 */
	public function generate_signature($user_id) {
		return $this->Auth->password($this->cookieName . $user_id . $_SERVER['HTTP_USER_AGENT']);
	}

	/**
	 * Delete the cookie.
	 *
	 * @access public
	 * @return void
	 */
	public function delete() {
		$this->Cookie->delete($this->cookieName);
	}
}
